# -*- coding: utf-8 -*-
import os
from google.appengine.ext.webapp import template
import cgi
import wsgiref.handlers
from google.appengine.ext.webapp.util import run_wsgi_app
import urllib
from google.appengine.api import urlfetch
from google.appengine.api import images
from google.appengine.api import mail
from google.appengine.ext import db
from google.appengine.ext import webapp
from django.utils import simplejson
import random
import pprint
import string
from django1fields import email_re
#from emailvalidator import email_address
from string import strip
import re

minimum_password_length = 3

LANG_EN = {
    "name":"Name",
    "photo":"Photo",
    "update":"Update",
    "people":"People",
    "password":"Password",
    "email":"Email Address",
}
LANG_ES = {
    "name":"Nombre",
    "photo":"Foto",
    "update":"Actualizar",
    "people":"Personas",
    "password":"Contraseña",
    "email":"Dirección de correo electrónico",
}
LANG = LANG_EN

class Member(db.Model):
    name = db.StringProperty()
    password = db.StringProperty()
    email = db.StringProperty()
    timeadded = db.DateTimeProperty(auto_now_add=True)

class LoginRecord(db.Model):
    code = db.StringProperty()
    member = db.ReferenceProperty(Member)
    timeadded = db.DateTimeProperty(auto_now_add=True)
    browser = db.StringProperty()
    ip = db.StringProperty()

class Photo(db.Model):
    member = db.ReferenceProperty(Member)
    filename = db.StringProperty()
    content = db.BlobProperty()
    thumb = db.BlobProperty()
    timeadded = db.DateTimeProperty(auto_now_add=True)
    

def logincookievalgenerate(membername):
    return membername+" "+(''.join([random.choice(string.letters + string.digits) for x in xrange(50)]))

def loginmember(member, self):
    # ok, set cookie
    cookieval = logincookievalgenerate(member.name)

    # store in db
    loginrec = LoginRecord()
    loginrec.code = cookieval
    loginrec.member = member
    loginrec.put()
    # todo browser, ip# logging
    self.response.headers.add_header( 'Set-Cookie', 'ack=%s; expires=Fri, 31-Dec-2030 23:59:59 GMT' % urllib.quote(cookieval))

def logincookievalmembernameget(cookieval):
    return cookieval.split(" ",1)[0]

def isloggedin(cookieval):
    # check if login
    logins = db.GqlQuery("SELECT * FROM LoginRecord WHERE code = :1", cookieval)
    if logins.count():
        login = logins.fetch(1)
        #split off member name part
        membername = logincookievalmembernameget(cookieval)
        
        # look up member
        result = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername)
        if result.count():
            member = result.fetch(1)[0]
            # return member
            return member
    
class MainPage(webapp.RequestHandler):
    def get(self):
        template_values = {
            'lang': LANG
            }  
        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))

class MemberEdit(webapp.RequestHandler):
    def get(self):
        name = urllib.unquote(self.request.cookies.get('ack', ''))
        template_values = {
            'name': name,
            'lang': LANG
            }
        path = os.path.join(os.path.dirname(__file__), 'member.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        # look for existing user, if doesn't exist create one, set cookie
        errmsg = ""
        tname = strip(self.request.get('name'))
        temail = strip(self.request.get('email'))
        tpassword = self.request.get('password')
        if (tname):
            mem = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", tname)
            if mem.count():
                errmsg = "username already taken, please try another"
            else:
                if len(tpassword) >= minimum_password_length:
                    # todo improve email checking algorithm
                    if email_re.match(temail):
                        # check if email has been used already
                        # eventually set it up so users can have multiple email addresses (or abstract out email part)
                        mem = db.GqlQuery("SELECT * FROM Member WHERE email = :1 LIMIT 1", temail)
                        if mem.count():
                            errmsg = "sorry, email already in use for another account"
                        else:
                            member = Member()
                            member.name = tname
                            member.password = tpassword
                            member.email = temail
                            member.put()
                            #if 'file' not in self.request.POST:
                                #self.error(400)
                                #self.response.out.write("please include a photo to upload")
                                #return
                            #if (self.request.POST.get('file', None) is None and not self.request.POST.get('file', None).filename):
                                #self.error(400)
                                #self.response.out.write("please include a photo to upload")
                                #return
                            if (self.request.POST.get('file')):
                                filedata = self.request.POST.get('file').file.read()
                                filename = self.request.POST.get('file').filename
                                photo = Photo()
                                photo.member = member
                                photo.filename = filename
                                photo.content = filedata
                                photo.put()
                            nameescaped = "a" #urllib
                            # todo log them in
                            loginmember(member, self)
                            errmsg = "successful"
                    else:
                        errmsg = "bad email"
                else:
                    errmsg = "password not long enough"
        else:
            errmsg = "missing username"
        template_values = {
            'lang': LANG,
            'errmsg': errmsg,
            'nameencoded': tname,
            #urllib.quote(member.name.encode("utf-8")),          
            }
        path = os.path.join(os.path.dirname(__file__), 'memberprocess.html')
        self.response.out.write(template.render(path, template_values))

class Login(webapp.RequestHandler):
    def get(self):
        template_values = {
            'lang': LANG
            }
        path = os.path.join(os.path.dirname(__file__), 'login.html')
        self.response.out.write(template.render(path, template_values))
    def post(self):
        # check if pwd ok, look up user by username
        membername = self.request.get('name')
        cookieval = ""
        errmsg = ""
        #self.response.out.write(membername+"<br>");
        mem = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername).fetch(1)
        if mem[0]:
            member = mem[0]
            if self.request.get('password') == mem[0].password:
                loginmember(member, self)
            else:
                errmsg = "bad password"
                # todo processing for security
        else:
            errmsg = "no such user"
            # todo processing for security
        template_values = {
            'cookieval': cookieval,
            'errmsg': errmsg,
            'lang': LANG
            }
        path = os.path.join(os.path.dirname(__file__), 'loginprocess.html')
        self.response.out.write(template.render(path, template_values))

class Logout(webapp.RequestHandler):
    def get(self):
        # todo: function to deliver cookieval
        cookieval = urllib.unquote(self.request.cookies.get('ack', ''))
        #empty cookie
        # todo: parametrize expiry date et al?
        self.response.headers.add_header( 'Set-Cookie', 'ack=; expires=Fri, 31-Dec-2030 23:59:59 GMT')
        #empty login from db
        q = db.GqlQuery("SELECT * FROM LoginRecord WHERE code = :1", cookieval)
        logins = q.fetch(10) # todo revisit this 10 later
        for login in logins:
            login.delete()
        
class MemberList(webapp.RequestHandler):
    def get(self):
        members = db.GqlQuery("SELECT * FROM Member")
        for mem in members:
            self.response.out.write(mem.name)
            #self.response.out.write(mem.password)
            memphotos = db.GqlQuery("SELECT * FROM Photo WHERE member = :1", mem)
            if memphotos.count():
                memphoto = memphotos.fetch(1)
                self.response.out.write(str(memphotos.count())+" has photo! <img src=/image?member="+mem.name+">")
                if memphoto[0].thumb:
                    self.response.out.write(" has thumbnail! <img src=/image?size=thumb&member="+mem.name+">")
                else:
                    memphoto[0].thumb = images.resize(memphoto[0].content, 32, 32)
                    memphoto[0].put()
            self.response.out.write("<p>");

class GetImage(webapp.RequestHandler):
    def get(self):
        membername = self.request.get('member')
        #self.response.out.write(membername+"<br>");
        mem = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername).fetch(1)
        #self.response.out.write(mem[0].name+"<br>");
        if (mem):
            memphotos = db.GqlQuery("SELECT * FROM Photo WHERE member = :1 LIMIT 1", mem[0]).fetch(1)
            for memphoto in memphotos:
            #   self.response.out.write(memphoto.member.name);
                self.response.headers['Content-Type'] = 'image/jpeg'
                if self.request.get('size') == 'thumb':
                    self.response.headers['Content-Type'] = 'image/png'
                    self.response.out.write(memphoto.thumb)
                else:
                    self.response.headers['Content-Type'] = 'image/jpeg'
                    self.response.out.write(memphoto.content)


class LoginTest(webapp.RequestHandler):
    def get(self):
        member = isloggedin(urllib.unquote(self.request.cookies.get('ack', '')))
        if (member):
            self.response.out.write('Hello, '+member.name)
        else:
            self.response.out.write('Hello, -- no member '+self.request.cookies.get('ack', ''))

class LoginList(webapp.RequestHandler):
    def get(self):
        q = db.GqlQuery("SELECT * FROM LoginRecord")
        logins = q.fetch(50) # todo revisit this 50 later
        for login in logins:
            self.response.out.write(login.code+"<p>\n")

class ChangePassword(webapp.RequestHandler):
    def get(self):
        # present form
        template_values = {
            'lang': LANG
            }
        path = os.path.join(os.path.dirname(__file__), 'changepassword.html')
        self.response.out.write(template.render(path, template_values))
    def post(self):
        # look up user;
        cookieval = urllib.unquote(self.request.cookies.get('ack', ''))
        member = isloggedin(cookieval)
        message = ""
        if (member):
            #check pwd
            if self.request.get('oldpassword') == member.password:
                # check new password is confirmed and equals (todo: have client-side javascript do this too)
                if self.request.get('newpassword') == self.request.get('newpasswordconfirm'):
                    # upon success, delete all OTHER loginrecords from loginrecord for that user
                    # need to pull them out for that user
                    loginrecords = db.GqlQuery("SELECT * FROM LoginRecord WHERE member = :1", member)
                    for loginrecord in loginrecords:
                        if loginrecord.code != cookieval:
                            loginrecord.delete()
                    # update pwd
                    member.password = self.request.get('newpassword')
                    member.put()
                    message = "password changed"
                    #self.response.out.write("password changed<p>\n")
                    if member.email:
                        mail.send_mail(sender="google@adrianscott.com",
                                   to=member.email,
                                   subject="Password Changed",
                                   body="""
Your password has been changed.

If this was not approved by you, now would be a good time to panic.
""")
                else:
                    message = "new password wasn't typed in right, please go back and fix."
            else:
                message = "old password wasn't right."
        template_values = {
            'message': message,
            'lang': LANG
            }
        path = os.path.join(os.path.dirname(__file__), 'changepasswordprocess.html')
        self.response.out.write(template.render(path, template_values))    

class EmailValidator(webapp.RequestHandler):
  def get(self):
      for address in addresses:
        self.response.out.write("%s : %s<br>" % (repr(address), email_address.match(address)))
        if email_address.match(address):
            self.response.out.write("match<p>")
        else:
            self.response.out.write("nada<p>")
        self.response.out.write("2: %s : %s<br>" % (repr(address), email_re.match(address)))
        if email_re.match(address):
            self.response.out.write("match<p>")
        else:
            self.response.out.write("nada<p>")
            
application = webapp.WSGIApplication(
                                       [('/', MainPage),
                                        ('/member', MemberEdit),
                                        ('/memberlist', MemberList),
                                        ('/image', GetImage),
                                        ('/login', Login),
                                        ('/logout', Logout),
                                        ('/logintest', LoginTest),
                                        ('/changepassword', ChangePassword),
                                        #('/emailvalidator', EmailValidator),
                                        #('/loginlist', LoginList)
                                        ],
                                       debug=True)     
def main():
  run_wsgi_app(application)
  
if __name__ == "__main__":
  main()
